dash_charts.utils_static_toc⚓︎
Add a nested Table of Contents to any HTML file with BeautifulSoup and dominate.
View Source
"""Add a nested Table of Contents to any HTML file with BeautifulSoup and dominate."""
from bs4 import BeautifulSoup
from dominate import tags
TOC_KEYWORD = '{{toc}}'
"""Default string to replace in the specified file with the nested table of contents. Default is `{{toc}}`."""
def add_nested_list_item(l_index, l_string, level=1):
"""Add nested list items recursively.
Args:
l_index: numeric index of the list depth (note: 1-indexed)
l_string: string to show in the list element
level: current list depth. Optional and default is 1
"""
with tags.ul():
if l_index != level:
add_nested_list_item(l_index, l_string, level + 1)
else:
tags.li(f'H{l_index}: {l_string}')
def create_toc(html_text, header_depth=3):
"""Return the HTML for a nested table of contents based on the HTML file path.
Args:
html_text: HTML text
header_depth: depth of headers to show. Default is 3 (H1-H3)
Returns:
string: table of contents
"""
soup = BeautifulSoup(html_text, features='lxml')
h_lookup = {f'h{idx}': idx for idx in range(1, header_depth + 1)}
toc = tags.div()
for header in soup.findAll([*h_lookup.keys()]):
with toc:
add_nested_list_item(h_lookup[header.name], header.string)
# FIXME: Figure out how to make the header links work (i.e. when clicked in TOC go to the respective header)
# > `tags.a(header.string, f'#{header.string}')`?
return str(toc)
def write_toc(html_path, header_depth=3, toc_key=TOC_KEYWORD):
"""Write the nested table of contents to the specified file.
Args:
html_path: path to the HTML file
header_depth: depth of headers to show. Default is 3 (H1-H3)
toc_key: string to replace with the nested table of contents. Default is `TOC_KEYWORD`
Raises:
RuntimeError: if the key was not found in the file
"""
text = html_path.read_text()
if toc_key not in text:
raise RuntimeError(f'HTML file does not have the table of contents key ({toc_key}): {html_path}')
toc = create_toc(text, header_depth=header_depth)
html_path.write_text(text.replace('{{toc}}', toc))
Variables⚓︎
TOC_KEYWORD
Default string to replace in the specified file with the nested table of contents. Default is {{toc}}.
Functions⚓︎
add_nested_list_item⚓︎
def add_nested_list_item(
l_index,
l_string,
level=1
)
Add nested list items recursively.
Parameters:
| Name | Description |
|---|---|
| l_index | numeric index of the list depth (note: 1-indexed) |
| l_string | string to show in the list element |
| level | current list depth. Optional and default is 1 |
View Source
def add_nested_list_item(l_index, l_string, level=1):
"""Add nested list items recursively.
Args:
l_index: numeric index of the list depth (note: 1-indexed)
l_string: string to show in the list element
level: current list depth. Optional and default is 1
"""
with tags.ul():
if l_index != level:
add_nested_list_item(l_index, l_string, level + 1)
else:
tags.li(f'H{l_index}: {l_string}')
create_toc⚓︎
def create_toc(
html_text,
header_depth=3
)
Return the HTML for a nested table of contents based on the HTML file path.
Parameters:
| Name | Description |
|---|---|
| html_text | HTML text |
| header_depth | depth of headers to show. Default is 3 (H1-H3) |
Returns:
| Type | Description |
|---|---|
| string | table of contents |
View Source
def create_toc(html_text, header_depth=3):
"""Return the HTML for a nested table of contents based on the HTML file path.
Args:
html_text: HTML text
header_depth: depth of headers to show. Default is 3 (H1-H3)
Returns:
string: table of contents
"""
soup = BeautifulSoup(html_text, features='lxml')
h_lookup = {f'h{idx}': idx for idx in range(1, header_depth + 1)}
toc = tags.div()
for header in soup.findAll([*h_lookup.keys()]):
with toc:
add_nested_list_item(h_lookup[header.name], header.string)
# FIXME: Figure out how to make the header links work (i.e. when clicked in TOC go to the respective header)
# > `tags.a(header.string, f'#{header.string}')`?
return str(toc)
write_toc⚓︎
def write_toc(
html_path,
header_depth=3,
toc_key='{{toc}}'
)
Write the nested table of contents to the specified file.
Parameters:
| Name | Description |
|---|---|
| html_path | path to the HTML file |
| header_depth | depth of headers to show. Default is 3 (H1-H3) |
| toc_key | string to replace with the nested table of contents. Default is TOC_KEYWORD |
Raises:
| Type | Description |
|---|---|
| RuntimeError | if the key was not found in the file |
View Source
def write_toc(html_path, header_depth=3, toc_key=TOC_KEYWORD):
"""Write the nested table of contents to the specified file.
Args:
html_path: path to the HTML file
header_depth: depth of headers to show. Default is 3 (H1-H3)
toc_key: string to replace with the nested table of contents. Default is `TOC_KEYWORD`
Raises:
RuntimeError: if the key was not found in the file
"""
text = html_path.read_text()
if toc_key not in text:
raise RuntimeError(f'HTML file does not have the table of contents key ({toc_key}): {html_path}')
toc = create_toc(text, header_depth=header_depth)
html_path.write_text(text.replace('{{toc}}', toc))
Last update:
August 5, 2022
Created: August 5, 2022
Created: August 5, 2022